package comman.duke 
{
	import com.hurlant.crypto.Crypto;
	import com.hurlant.crypto.symmetric.ICipher;
	import com.hurlant.crypto.symmetric.IPad;
	import com.hurlant.crypto.symmetric.IVMode;
	import com.hurlant.crypto.symmetric.NullPad;
	import com.hurlant.util.Base64;
	import com.hurlant.util.Hex;
	import flash.external.ExternalInterface;
	import flash.utils.ByteArray;
	/**
	 * ...
	 * @author jerry.d
	 */
	public class GameUtils 
	{
		public static var ReferDate:Date = new Date();
		public static var DEBUG_LEVEL:uint = 0;
		public static const INFO:uint = 1;
		public static const LOG:uint = 0;
		public static const FATAL:uint = 2;
		
		public static function alert(info:String):void{
			if ( ExternalInterface.available){
				ExternalInterface.call('alert', info);
			}
		}
		/**
		 * 断言
		 * */
		public static function assert(expression:Boolean, ...args):void{
			if ( expression ){
				return;
			}
			_assert(args);
		}
		
		private static function _assert(args:Array):void{
			ReferDate.setTime(TickerMgr.SYSTIME);
			var logInfo:String = "【assert】"+GetTimeString(FrameMgr.referTime - FrameMgr.startTime)+" -> "+args.join(' ' );
			if ( ExternalInterface.available){
				ExternalInterface.call('log', logInfo);
			}else{
				trace(logInfo);
			}
		}
		
		/**
		 * info
		 * */
		public static function info(...args):void{
			if ( DEBUG_LEVEL > INFO) return;
			ReferDate.setTime(TickerMgr.SYSTIME);
			var logInfo:String = "【info】"+GetTimeString(FrameMgr.referTime - FrameMgr.startTime)+" -> "+args.join(' ');
			if ( ExternalInterface.available){
				ExternalInterface.call('log', logInfo);
			}else{
				trace(logInfo);
			}
		}
		/**
		 * log
		 * */
		public static function log(...args):void{
			if ( DEBUG_LEVEL > LOG) return;
			var logInfo:String = "【log】"+GetTimeString(FrameMgr.referTime - FrameMgr.startTime)+" -> "+args.join(' ');
			if ( ExternalInterface.available){
				ExternalInterface.call('log', logInfo);
			}else{
				trace(logInfo);
			}
		}
		/**
		 * fatal
		 * */
		public static function fatal(...args):void{
			if ( DEBUG_LEVEL > FATAL) return;
			ReferDate.setTime(TickerMgr.SYSTIME);
			var logInfo:String = "【fatal】"+GetTimeString(FrameMgr.referTime - FrameMgr.startTime)+" -> "+args.join(' ');
			if ( ExternalInterface.available){
				ExternalInterface.call('log', logInfo);
			}else{
				trace(logInfo);
			}
		}
		/**
		 * millsecond per 1 minute
		 * */
		public static const MINUTE:uint = 60000;
		/**
		 * millseconds per 1 hour
		 * */
		public static const HOUR:uint = 1000 * 60 * 60;
		public static function GetTimeString(times:uint,model:String='[hour]:[min]:[sec]'):String{
			var hour:int = int(times/HOUR);
			var minutes:int = int((times - HOUR*hour) / MINUTE);
			var seconds:int = int((times - HOUR * hour - MINUTE * minutes) / 1000);
			return model.replace('[hour]', hour>=10?hour :('0'+hour)).replace('[min]', minutes>=10?minutes:('0'+minutes)).replace('[sec]', seconds>=10?seconds:('0'+seconds));
		}
		/**
		 * millseconds from 1970,01,01
		 * **/
		public static function GetDateTime(time:Number):String{
			ReferDate.setTime(time);
			var hour:int = ReferDate.getHours();
			var minutes:int = ReferDate.getMinutes();
			var seconds:int = ReferDate.getSeconds();
			return (hour>=10?hour :('0'+hour)) + ":" + (minutes>=10?minutes:('0'+minutes)) + ":" + (seconds>=10?seconds:('0'+seconds));
		}
		
		/**
		 * Number to String, and add splitor
		 * @author jerry.d
		 * 
		 * **/
		public static function NumberToString(num:Number, splitor:String = ",",toFixed:int=2):String{
			var isNeg:Boolean = false;
			if ( num < 0 ){
				isNeg = true;
				num = -num;
			}
			if ( num < 1000){
				return num.toFixed(toFixed);
			}
			
			var str:String = num.toFixed(toFixed);
			var dotIndex:int = str.indexOf(".");
			
			var result:String = "";
			if ( dotIndex == -1){
				var len:int = str.length;
				var index:int = 1;
				while ( index * 3 <= len){
					result = result != "" ? str.substr(len - index * 3, 3) +splitor+ result : str.substr(len-index*3,3);
					index++;
				}
				if ( len % 3 != 0){
					return str.substr(0,len-(index-1)*3)+splitor+result;
				}else{
					return result;
				}
				
			}else{
				var substr:String = str.substr(0, dotIndex);
				len = substr.length;
				result = "";
				index = 1;
				while ( index * 3 <= len){
					result = result != "" ? substr.substr(len - index * 3, 3) +splitor+ result : substr.substr(len - index * 3, 3);
					index++;
				}
				
				if ( len % 3 != 0){
					return substr.substr(0,len-(index-1)*3)+splitor+result+str.substr(dotIndex);
				}else{
					return result+str.substr(dotIndex);
				}
			}
		}
		
		public static function md5(e:String):String{
			var t:Array = [];
			var n:uint;
			var r:uint;
			var i:uint;
			var s:uint;
			var o:uint;
			var u:uint; 
			var a:uint;
			var f:uint; 
			var l:uint;
			var c:uint = 7;
			var h:uint = 12;
			var p:uint = 17;
			var d:uint = 22;
			var v:uint = 5;
			var m:uint = 9;
			var g:uint = 14;
			var y:uint = 20;
			var b:uint = 4;
			var w:uint = 11;
			var E:uint = 16;
			var S:uint = 23;
			var x:uint = 6; 
			var T:uint = 10;
			var N:uint = 15;
			var C:uint = 21;
			e = uTF8Encode(e);
			t = convertToWordArray(e);
			u = 1732584193;
			a = 4023233417;
			f = 2562383102;
			l = 271733878;
			for (n = 0; n < t.length; n += 16){
				r = u;
				i = a;
				s = f;
				o = l;
				u = FF(u, a, f, l, t[n + 0], c, 3614090360);
				l = FF(l, u, a, f, t[n + 1], h, 3905402710);
				f = FF(f, l, u, a, t[n + 2], p, 606105819);
				a = FF(a, f, l, u, t[n + 3], d, 3250441966);
				u = FF(u, a, f, l, t[n + 4], c, 4118548399);
				l = FF(l, u, a, f, t[n + 5], h, 1200080426);
				f = FF(f, l, u, a, t[n + 6], p, 2821735955);
				a = FF(a, f, l, u, t[n + 7], d, 4249261313);
				u = FF(u, a, f, l, t[n + 8], c, 1770035416);
				l = FF(l, u, a, f, t[n + 9], h, 2336552879);
				f = FF(f, l, u, a, t[n + 10], p, 4294925233);
				a = FF(a, f, l, u, t[n + 11], d, 2304563134);
				u = FF(u, a, f, l, t[n + 12], c, 1804603682);
				l = FF(l, u, a, f, t[n + 13], h, 4254626195);
				f = FF(f, l, u, a, t[n + 14], p, 2792965006);
				a = FF(a, f, l, u, t[n + 15], d, 1236535329);
				u = GG(u, a, f, l, t[n + 1], v, 4129170786);
				l = GG(l, u, a, f, t[n + 6], m, 3225465664);
				f = GG(f, l, u, a, t[n + 11], g, 643717713);
				a = GG(a, f, l, u, t[n + 0], y, 3921069994);
				u = GG(u, a, f, l, t[n + 5], v, 3593408605);
				l = GG(l, u, a, f, t[n + 10], m, 38016083);
				f = GG(f, l, u, a, t[n + 15], g, 3634488961);
				a = GG(a, f, l, u, t[n + 4], y, 3889429448);
				u = GG(u, a, f, l, t[n + 9], v, 568446438);
				l = GG(l, u, a, f, t[n + 14], m, 3275163606);
				f = GG(f, l, u, a, t[n + 3], g, 4107603335);
				a = GG(a, f, l, u, t[n + 8], y, 1163531501);
				u = GG(u, a, f, l, t[n + 13], v, 2850285829);
				l = GG(l, u, a, f, t[n + 2], m, 4243563512);
				f = GG(f, l, u, a, t[n + 7], g, 1735328473);
				a = GG(a, f, l, u, t[n + 12], y, 2368359562);
				u = HH(u, a, f, l, t[n + 5], b, 4294588738);
				l = HH(l, u, a, f, t[n + 8], w, 2272392833);
				f = HH(f, l, u, a, t[n + 11], E, 1839030562);
				a = HH(a, f, l, u, t[n + 14], S, 4259657740);
				u = HH(u, a, f, l, t[n + 1], b, 2763975236);
				l = HH(l, u, a, f, t[n + 4], w, 1272893353);
				f = HH(f, l, u, a, t[n + 7], E, 4139469664);
				a = HH(a, f, l, u, t[n + 10], S, 3200236656);
				u = HH(u, a, f, l, t[n + 13], b, 681279174);
				l = HH(l, u, a, f, t[n + 0], w, 3936430074);
				f = HH(f, l, u, a, t[n + 3], E, 3572445317);
				a = HH(a, f, l, u, t[n + 6], S, 76029189);
				u = HH(u, a, f, l, t[n + 9], b, 3654602809);
				l = HH(l, u, a, f, t[n + 12], w, 3873151461);
				f = HH(f, l, u, a, t[n + 15], E, 530742520);
				a = HH(a, f, l, u, t[n + 2], S, 3299628645);
				u = II(u, a, f, l, t[n + 0], x, 4096336452);
				l = II(l, u, a, f, t[n + 7], T, 1126891415);
				f = II(f, l, u, a, t[n + 14], N, 2878612391);
				a = II(a, f, l, u, t[n + 5], C, 4237533241);
				u = II(u, a, f, l, t[n + 12], x, 1700485571);
				l = II(l, u, a, f, t[n + 3], T, 2399980690);
				f = II(f, l, u, a, t[n + 10], N, 4293915773);
				a = II(a, f, l, u, t[n + 1], C, 2240044497);
				u = II(u, a, f, l, t[n + 8], x, 1873313359);
				l = II(l, u, a, f, t[n + 15], T, 4264355552);
				f = II(f, l, u, a, t[n + 6], N, 2734768916);
				a = II(a, f, l, u, t[n + 13], C, 1309151649);
				u = II(u, a, f, l, t[n + 4], x, 4149444226);
				l = II(l, u, a, f, t[n + 11], T, 3174756917);
				f = II(f, l, u, a, t[n + 2], N, 718787259);
				a = II(a, f, l, u, t[n + 9], C, 3951481745);
				u = addUnsigned(u, r);
				a = addUnsigned(a, i);
				f = addUnsigned(f, s);
				l = addUnsigned(l, o)
				
			}
			var k:String = wordToHex(u) + wordToHex(a) + wordToHex(f) + wordToHex(l);
			return k.toLowerCase();
				
		}
		
		private static function rotateLeft(e:uint, t:uint):uint{
			return e << t | e >>> 32 - t;
		}
	
		private static function addUnsigned(e:uint, t:uint):uint{
			var n:uint;
			var r:uint;
			var i:uint;
			var s:uint;
			var o:uint;
			i = e & 2147483648;
			s = t & 2147483648;
			n = e & 1073741824;
			r = t & 1073741824;
			o = (e & 1073741823) + (t & 1073741823);
			if (n & r)
				return o ^ 2147483648 ^ i ^ s;
			if (n | r){
				if (o & 1073741824)
					return o ^ 3221225472 ^ i ^ s;
					else 
						return o ^ 1073741824 ^ i ^ s;
						
			}else{
				return o ^ i ^ s;
				
			}
			
		}
		private static function F(e:uint, t:uint, n:uint):uint{
			return e & t | ~e & n;
				
		}
		private static function G(e:uint, t:uint, n:uint):uint{
			return e & n | t & ~n;
				
		}
		private static function H(e:uint, t:uint, n:uint):uint{
			return e ^ t ^ n;
			
		}
		private static function I(e:uint, t:uint, n:uint):uint{
				return t^(e|~n)
				
		}
		private static function FF(e:uint, t:uint, n:uint, r:uint, i:uint, s:uint, o:uint):uint{
			e = addUnsigned(e, addUnsigned(addUnsigned(F(t, n, r), i), o));
			return addUnsigned(rotateLeft(e,s),t)
			
		}
		private static function GG(e:uint, t:uint, n:uint, r:uint, i:uint, s:uint, o:uint):uint{
			e = addUnsigned(e, addUnsigned(addUnsigned(G(t, n, r), i), o));
			return addUnsigned(rotateLeft(e,s),t)
			
		}
		private static function HH(e:uint, t:uint, n:uint, r:uint, i:uint, s:uint, o:uint):uint{
			e = addUnsigned(e, addUnsigned(addUnsigned(H(t, n, r), i), o));
			return addUnsigned(rotateLeft(e,s),t)
			
		}
		private static function II(e:uint, t:uint, n:uint, r:uint, i:uint, s:uint, o:uint):uint{
			e = addUnsigned(e, addUnsigned(addUnsigned(I(t, n, r), i), o));
			return addUnsigned(rotateLeft(e,s),t)
			
		}
		private static function convertToWordArray(e:String):Array{
			var t:uint;
			var n:uint = e.length;
			var r:uint = n + 8;
			var i:uint = (r - r % 64) / 64;
			var s:uint = (i + 1) * 16;
			var o:Array = new Array(s - 1);
			var u:uint = 0;
			var a:uint = 0;
			while (a < n){
				t = (a - a % 4) / 4;
				u = a % 4 * 8;
				o[t] = o[t] | e.charCodeAt(a) << u;
				a++
				
			}
			t = (a - a % 4) / 4;
			u = a % 4 * 8;
			o[t] = o[t] | 128 << u;
			o[s - 2] = n << 3;
			o[s - 1] = n >>> 29;
			return o
			
		}
		private static function wordToHex(e:uint):String{
			var t:String = "";
			var n:String = "";
			var r:uint; 
			var i:uint;
			for (i = 0; i <= 3; i++){
				r = e >>> i * 8 & 255;
				n = "0" + r.toString(16);
				t=t+n.substr(n.length-2,2)
				
			}
			return t
			
		}
		private static function uTF8Encode(e:String):String{
			e = e.replace(/\x0d\x0a/g, "\n");
			var t:String = "";
			for (var n:uint = 0; n < e.length; n++){
				var r:uint = e.charCodeAt(n);
				if (r < 128){
					t+=String.fromCharCode(r)
					
				}else if (r > 127 && r < 2048){
					t += String.fromCharCode(r >> 6 | 192);
					t+=String.fromCharCode(r&63|128)
					
				}else{
					t += String.fromCharCode(r >> 12 | 224);
					t += String.fromCharCode(r >> 6 & 63 | 128);
					t+=String.fromCharCode(r&63|128)
					
				}
				
			}
			return t;
			
		}
		
		public static const unique:String = 'KoDU7d7DZai95GiQqd/wVohVJ+LLJdFuBnvx0SSC9SzlDMA7MdEwUMokZt4cQpXtpVSc6Lgq01+KMza/m/5fVg==';
	}

}